#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include "user.h"
#include "common.h"
#include "upper.h"
#include "part.h"
#include "usermanager.h"

user_socket* user_array[MAX_LOGINS] = {0};

#define LOGIN_OUTTIME           (60*20)

void login_timeout(void* param);

user_socket* create_user(void){
    user_socket* user = (user_socket*)malloc(sizeof(user_socket));
    memset(user,0,sizeof(user_socket));
    return user;
}

void add_to_user_array(user_socket* p_user,char* username){
    int i;
    for(i=0;i<MAX_LOGINS;i++){
        if(user_array[i] == NULL){            
            p_user->username = username;
            timer_stop(p_user->login_timeout_timer);        
            user_array[i] = p_user;
            write_log("%s has login",p_user->username);
            break;
        }
    }
}

void del_from_user_array(user_socket* p_user){
    int i;
    for(i=0;i<MAX_LOGINS;i++){
        if(user_array[i] == p_user){
            close(p_user->sock);
            timer_stop(p_user->login_timeout_timer);
            write_log("%s has login out",p_user->username);
            free(p_user);
            user_array[i] = NULL;
            break;
        }
    }  
}

void init_user(user_socket* p_user){
    int keep_alive = 1;
    int keep_idle = 60;
    int keep_interval = 5;
    int keep_count = 3;

    setsockopt(p_user->sock,SOL_SOCKET,SO_KEEPALIVE,(void*)&keep_alive,4);
    setsockopt(p_user->sock,SOL_TCP,TCP_KEEPIDLE,(void*)&keep_idle,4);
    setsockopt(p_user->sock,SOL_TCP,TCP_KEEPINTVL,(void*)&keep_interval,4);
    setsockopt(p_user->sock,SOL_TCP,TCP_KEEPCNT,(void*)&keep_count,4);

    p_user->login_timeout_timer = timer_start(login_timeout,LOGIN_OUTTIME,p_user,0);
}



void login_timeout(void* param){
    user_socket* user;
    if(param){
        user = (user_socket*)param;
#ifndef DEBUG        
        user->exit = 1;
#endif
    } 
}

void* user_thread(void* param){
    user_socket* p_user = (user_socket*)param;
    int ret;
    char recv_buff[2*1024*1024] = {0};
    char send_buff[10*1024] = {0};
    char* p;
    int sl;
    fd_set readfds;
    fd_set writefds;
    fd_set errorfds;
    struct timeval timeout = {0};
    init_user(p_user);
    
    while(!p_user->exit){
        timeout.tv_sec = 1;
        FD_SET(p_user->sock,&readfds);
        FD_SET(p_user->sock,&writefds);
        FD_SET(p_user->sock,&errorfds);
        ret = select(p_user->sock+1,&readfds,NULL,&errorfds,&timeout); 
        if(ret > 0){
            if(FD_ISSET(p_user->sock,&readfds)){
                memset(recv_buff,0,sizeof(recv_buff));
                ret = recv(p_user->sock,recv_buff,sizeof(recv_buff)-1,0);
                if(ret > 0){                                            
                    if(recv_buff[0] == '{' && strcmp(END_MARK,&recv_buff[ret-END_LENGTH]) == 0){     
                        recv_buff[ret-4] = 0; 
                        printf_comm_flag(COM_RX,print_upper,p_user->username,recv_buff,strlen(recv_buff));                                                                          
                        p = parse_upper_protocol(recv_buff,p_user);
                        if(p){
                            sprintf(send_buff,"%s%s",p,END_MARK);
                            printf_comm_flag(COM_TX,print_upper,p_user->username,send_buff,strlen(send_buff));
                            send(p_user->sock,send_buff,strlen(send_buff),0);
                            free(p);
                        }
                    }                    
                }
                else{                 
                    userloginout(p_user->username,p_user);
                    p_user->exit = 1;
                }
            }            
        }

        if(p_user->alarm_sample_flag){
            p_user->alarm_sample_flag = 0;
            scan_alarm(p_user);
        }
    }
    del_from_user_array(p_user);
    printf("user exit\n");
}